home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / et / et-2_2.lha / et2.2 / src / VObject.C < prev    next >
C/C++ Source or Header  |  1990-12-21  |  20KB  |  1,007 lines

  1. //$VObject,VObjectMover,VObjectStretcher,CompositeVObject,VObjectCommand$
  2.  
  3. #include "VObject.h" 
  4. #include "Menu.h"
  5. #include "BlankWin.h"
  6. #include "WindowSystem.h"
  7. #include "String.h"
  8. #include "OrdColl.h"
  9.  
  10. //---- VObject -----------------------------------------------------------------
  11.  
  12. AbstractMetaImpl(VObject, (TP(container), T(id), T(contentRect), 0));
  13.  
  14. VObject::VObject(EvtHandler *next, Rectangle r, int id)
  15. {
  16.     Init(id, r, (View*) next);
  17. }
  18.  
  19. VObject::VObject(Rectangle r, int id)
  20. {
  21.     Init(id, r, 0);
  22. }
  23.  
  24. VObject::VObject(int id)
  25. {
  26.     Init(id, gRect0, 0);
  27. }
  28.  
  29. void VObject::Init(int i, Rectangle r, View *v)
  30. {
  31.     VObject::SetContainer(v);
  32.     id= i;
  33.     contentRect= r;
  34.     SetFlag(eVObjDefault+eVObjOpen);
  35. }
  36.  
  37. char *VObject::AsString()
  38. {
  39.     return "~";
  40. }
  41.  
  42. int VObject::Compare(ObjPtr op)
  43. {
  44.     return StrCmp((byte*)AsString(), (byte*)op->AsString(), -1, sortmap);
  45. }
  46.  
  47. bool VObject::IsEqual(ObjPtr op)
  48. {
  49.     return StrCmp((byte*)AsString(), (byte*)op->AsString(), -1, sortmap) == 0;
  50. }
  51.  
  52. //---- state -------------------------------------------------------------------
  53.  
  54. void VObject::Open(bool mode)
  55. {
  56.     SetFlag(eVObjOpen, mode);
  57. }
  58.  
  59. void VObject::Enable(bool b, bool redraw)
  60. {
  61.     SetFlag(eVObjEnabled, b);
  62.     if (redraw)
  63.     ForceRedraw();
  64. }
  65.  
  66. //---- container ---------------------------------------------------------------
  67.  
  68. void VObject::SetContainer(VObject *v)
  69. {
  70.     container= v;
  71. }
  72.  
  73. VObject *VObject::FindContainerOfClass(Class *cla)
  74. {
  75.     register VObject *vp;
  76.     
  77.     if (cla == Meta(BlankWin))
  78.     vp= this;
  79.     else
  80.     vp= GetContainer();
  81.     
  82.     for (; vp; vp= vp->GetContainer()) {
  83.     if (vp->IsA()->isKindOf(cla))
  84.         return vp;
  85.     }
  86.     return 0;
  87. }
  88.  
  89. Point VObject::ContainerPoint(Point p)
  90. {
  91.     return p;
  92. }
  93.  
  94. Point VObject::GetPortPoint(Point p)
  95. {
  96.     p= ContainerPoint(p);
  97.     if (GetContainer())
  98.     return GetContainer()->GetPortPoint(p);
  99.     return p;
  100. }
  101.  
  102. BlankWin *VObject::GetWindow()
  103. {
  104.     return (BlankWin*) FindContainerOfClass(Meta(BlankWin));
  105. }
  106.  
  107. View *VObject::GetView()
  108. {
  109.     return (View*) FindContainerOfClass(Meta(View));
  110. }
  111.  
  112. Clipper *VObject::Getclipper()
  113. {
  114.     return (Clipper*) FindContainerOfClass(Meta(Clipper));
  115. }
  116.  
  117. void VObject::AddToClipper(class Clipper *clipper)
  118. {
  119.     VObject::SetContainer(clipper);
  120.     CalcExtent();
  121.     SetOrigin(gPoint0);
  122. }
  123.  
  124. void VObject::RemoveFromClipper(class Clipper *clipper)
  125. {
  126.     if (GetContainer() == clipper)
  127.     SetContainer(0);
  128. }
  129.  
  130. Rectangle VObject::GetViewedRect()
  131. {
  132.     return contentRect;
  133. }
  134.  
  135. void VObject::SetFocus(Rectangle r, Point o)
  136. {
  137.     if (GetContainer() && r.Clip(contentRect))
  138.     GetContainer()->SetFocus(r, o);
  139. }
  140.  
  141. //---- tree walking ------------------------------------------------------------
  142.  
  143. VObject *VObject::Detect(BoolFun find, void *arg)
  144. {
  145.     if (find(this, this, arg))
  146.     return this;
  147.     return 0;
  148. }
  149.  
  150. static bool Comp1(Object*, Object *op, void *v)
  151. {
  152.     return (bool) (((VObject*)(op))->GetId() == (int)v);
  153. }
  154.  
  155. static bool Comp2(Object*, Object *op, void *v)
  156. {
  157.     VObject *vop= (VObject*) op;
  158.     Point p= *((Point*)v);
  159.     Point offset= vop->ContainerPoint(gPoint0);
  160.     return (bool) vop->ContainsPoint(p-offset);
  161. }
  162.  
  163. static bool Comp3(Object*, Object *op, void *v)
  164. {
  165.     return op->IsEqual((VObject*)v);
  166. }
  167.  
  168. static bool Comp4(Object*, Object *op, void *v)
  169. {
  170.     return op == (VObject*)v;
  171. }
  172.  
  173. VObject *VObject::FindItem(int id)
  174. {
  175.     if (id != cIdNone)
  176.     return Detect(Comp1, (void*) id);
  177.     return 0;
  178. }
  179.  
  180. VObject *VObject::FindItem(Point p)
  181. {
  182.     return Detect(Comp2, &p);
  183. }
  184.  
  185. VObject *VObject::FindItem(VObject *g)
  186. {
  187.     return Detect(Comp3, g);
  188. }
  189.  
  190. VObject *VObject::FindItemPtr(VObject *g)
  191. {
  192.     return Detect(Comp4, g);
  193. }
  194.  
  195. //---- layout ------------------------------------------------------------------
  196.  
  197. Metric VObject::GetMinSize()
  198. {
  199.     return Metric(contentRect.extent);
  200. }
  201.  
  202. void VObject::CalcExtent()
  203. {
  204.     SetExtent(GetMinSize().Extent());
  205. }
  206.  
  207. int VObject::Base()
  208.     return contentRect.extent.y;
  209. }
  210.  
  211. void VObject::SetOrigin(Point origin)
  212. {
  213.     if (contentRect.origin != origin) {
  214.     contentRect.origin= origin;
  215.     if (TestFlag(eVObjLayoutCntl)) 
  216.         Control(GetId(), cPartOriginChanged, this);
  217.     Object::Send(GetId(), cPartOriginChanged, &origin);
  218.     }
  219. }
  220.  
  221. void VObject::SetExtent(Point extent)
  222. {
  223.     if (contentRect.extent != extent) {
  224.     contentRect.extent= extent;
  225.     if (TestFlag(eVObjLayoutCntl)) 
  226.         Control(GetId(), cPartExtentChanged, this);
  227.     Object::Send(GetId(), cPartExtentChanged, &extent);
  228.     }
  229. }
  230.  
  231. void VObject::SetContentRect(Rectangle r, bool redraw)
  232. {
  233.     if (!redraw && contentRect == r)
  234.     return;
  235.     if (redraw)
  236.     ForceRedraw();
  237.     if (contentRect.extent != r.extent)
  238.     SetExtent(r.extent);
  239.     SetOrigin(r.origin);
  240.     if (redraw)
  241.     ForceRedraw();
  242. }
  243.  
  244. void VObject::Align(Point at, Metric m, VObjAlign ga)
  245. {
  246.     switch (ga & eVObjH) {
  247.     case eVObjHLeft:
  248.     break;
  249.     case eVObjHCenter:
  250.     at.x+= (m.Width() - Width())/2;
  251.     break;
  252.     case eVObjHRight:
  253.     at.x+= m.Width() - Width();
  254.     break;
  255.     }
  256.     switch (ga & eVObjV) {
  257.     case eVObjVBase:
  258.     at.y+= m.Base() - Base();
  259.     break;
  260.     case eVObjVCenter:
  261.     at.y+= (m.Height() - Height())/2;
  262.     break;
  263.     case eVObjVBottom:
  264.     at.y+= m.Height() - Height();
  265.     break;
  266.     }
  267.     SetOrigin(at);
  268. }
  269.  
  270. void VObject::Move(Point delta, bool redraw)
  271. {
  272.     if (delta == gPoint0)
  273.     return;
  274.     if (redraw)
  275.     ForceRedraw();
  276.     SetOrigin(GetOrigin()+delta);
  277.     if (redraw) {
  278.     ForceRedraw();
  279.     Changed();
  280.     }
  281. }
  282.  
  283. //---- resizing ----------------------------------------------------------------
  284.  
  285. Command *VObject::GetMover()
  286. {
  287.     VObject *v= GetView();
  288.     if (v)
  289.     return new VObjectMover(this, v->contentRect);
  290.     return new VObjectMover(this);
  291. }
  292.  
  293. Command *VObject::GetStretcher()
  294. {
  295.     VObject *v= GetView();
  296.     if (v)
  297.     return new VObjectStretcher(this, v->contentRect);
  298.     return new VObjectStretcher(this);
  299. }
  300.  
  301. bool VObject::ContainsPoint(Point p)
  302. {
  303.     return contentRect.ContainsPoint(p);
  304. }
  305.  
  306. //---- drawing -----------------------------------------------------------------
  307.  
  308. static VObject *aetsch= 0;
  309.  
  310. void VObject::DrawAll(Rectangle r, bool highlight)
  311. {
  312.     if (IsOpen() && r.Clip(contentRect))
  313.     DrawInner(r, (bool) (highlight || aetsch == this));
  314. }
  315.  
  316. void VObject::DrawInner(Rectangle r, bool highlight)
  317. {
  318.     if (!GrHasColor())
  319.     Draw(r);
  320.     if (highlight && ! gPrinting) {
  321.     GrSetPattern(gHighlightColor);
  322.     GrSetPenPattern(gHighlightColor);
  323.     DrawHighlight(r);
  324.     GrSetPattern(ePatBlack);
  325.     GrSetPenNormal();
  326.     }
  327.     if (GrHasColor())
  328.     Draw(r);
  329. }
  330.  
  331. void VObject::Draw(Rectangle r)
  332. {
  333. }
  334.  
  335. void VObject::DrawHighlight(Rectangle r)
  336. {
  337.     GrFillRect(r);
  338. }
  339.  
  340. void VObject::Highlight(HighlightState hst)
  341. {
  342.     if (hst)
  343.     aetsch= this;
  344.     ForceRedraw();
  345.     UpdateEvent();
  346.     aetsch= 0;
  347. }
  348.  
  349. void VObject::Outline2(Point p1, Point p2)
  350. {
  351.     GrStrokeRect(NormRect(p1, p2));
  352. }
  353.  
  354. void VObject::OutlineRect(Rectangle r)
  355. {
  356.     Outline2(r.NW(), r.SE());
  357. }
  358.  
  359. void VObject::Outline(Point delta)
  360. {
  361.     OutlineRect(contentRect+delta);
  362. }
  363.  
  364. //---- invalidation and focusing -----------------------------------------------
  365.  
  366. void VObject::InvalidateRect(Rectangle r)
  367. {
  368.     if (r.Clip(contentRect) && IsOpen() && GetContainer())
  369.     GetContainer()->InvalidateViewRect(r);
  370. }
  371.  
  372. void VObject::InvalidateViewRect(Rectangle r)
  373. {
  374.     r.origin= ContainerPoint(r.origin);
  375.     InvalidateRect(r);
  376. }
  377.  
  378. void VObject::ForceRedraw()
  379.     InvalidateRect(contentRect); 
  380. }
  381.  
  382. void VObject::UpdateEvent()
  383. {
  384.     if (IsOpen() && GetContainer())
  385.     GetContainer()->UpdateEvent();
  386. }
  387.  
  388. GrCursor VObject::GetCursor(Point lp)
  389. {
  390.     if (GetContainer())
  391.     return GetContainer()->GetCursor(ContainerPoint(lp));
  392.     return eCrsBoldArrow;
  393. }
  394.  
  395. //---- input/output ------------------------------------------------------------
  396.  
  397. ostream& VObject::PrintOn(ostream &s)
  398. {
  399.     EvtHandler::PrintOn(s);
  400.     return s << id SP << contentRect SP;
  401. }
  402.  
  403. istream& VObject::ReadFrom(istream &s)
  404. {
  405.     EvtHandler::ReadFrom(s);
  406.     return s >> id >> contentRect;
  407. }
  408.  
  409. //---- input handling ----------------------------------------------------------
  410.  
  411. EvtHandler *VObject::GetNextHandler()
  412. {
  413.     return GetContainer();
  414. }
  415.  
  416. void VObject::DoOnItem(int, VObject*, Point)
  417. {
  418. }
  419.  
  420. Command *VObject::Input(Point lp, Token t, Clipper *vf)
  421. {
  422.     if (ContainsPoint(lp) /* && IsOpen() */) {
  423.     if (Enabled())
  424.         return DispatchEvents(lp, t, vf);
  425.     return gNoChanges;
  426.     }
  427.     return 0;     
  428. }
  429.  
  430. Command *VObject::DispatchEvents(Point lp, Token t, Clipper *vf)
  431. {
  432.     extern int Clicks;
  433.     register Command *currCmd= gNoChanges;
  434.     
  435.     if (t.IsMouseButton() || t.Code == eEvtEnter || t.Code == eEvtExit 
  436.             || t.Code == eEvtLocMove || t.Code == eEvtLocStill)
  437.     GrSetCursor(GetCursor(lp));
  438.  
  439.     switch (t.Code) {
  440.     case eEvtRightButton:
  441.     if (!(t.Flags & eFlgButDown))
  442.         currCmd= DoRightButtonDownCommand(lp, t, Clicks, vf);
  443.     break;
  444.     case eEvtMiddleButton:
  445.     case eEvtLeftButton:
  446.     if (!(t.Flags & eFlgButDown)) {
  447.         if (t.Code == eEvtLeftButton) {
  448.         if (t.Flags == (eFlgShiftKey|eFlgCntlKey|eFlgMetaKey))
  449.             Inspect();
  450.         else
  451.             currCmd= DoLeftButtonDownCommand(lp, t, Clicks);
  452.         } else
  453.         currCmd= DoMiddleButtonDownCommand(lp, t, Clicks);
  454.         if (currCmd && currCmd != gNoChanges && vf)
  455.         currCmd= vf->TrackInContent(lp, t, currCmd);
  456.     }
  457.     break;
  458.     default:
  459.     if (t.IsKey())
  460.         currCmd= DoKeyCommand(t.Code, lp, t);
  461.     else if (t.IsFunctionKey()) 
  462.         currCmd= DoFunctionKeyCommand(t.FunctionCode(), lp, t);
  463.     else if (t.IsCursorKey())
  464.         currCmd= DoCursorKeyCommand(t.CursorDir(), lp, t);
  465.     else if (t.Code == eEvtIdle)
  466.         currCmd= DoIdleCommand();
  467.     else
  468.         currCmd= DoOtherEventCommand(lp, t);
  469.     break;
  470.     }
  471.     return currCmd;
  472. }
  473.  
  474. Command *VObject::DoKeyCommand(int ch, Point lp, Token t)
  475. {
  476.     if (GetContainer())
  477.     return GetContainer()->DoKeyCommand(ch, ContainerPoint(lp), t);
  478.     return gNoChanges;
  479. }
  480.  
  481. Command *VObject::DoCursorKeyCommand(EvtCursorDir d, Point p, Token t)
  482. {
  483.     if (GetContainer())
  484.     return GetContainer()->DoCursorKeyCommand(d, ContainerPoint(p), t);
  485.     return gNoChanges;
  486. }
  487.  
  488. Command *VObject::DoFunctionKeyCommand(int pfk, Point lp, Token t)
  489. {
  490.     int code= -1;
  491.     
  492.     switch (t.FunctionCode()) {
  493.     case 3:
  494.     code= cUNDO;
  495.     break;
  496.     case 5:
  497.     code= cCOPY;
  498.     break;
  499.     case 4:
  500.     code= cTOP;
  501.     break;
  502.     case 7:
  503.     code= cPASTE;
  504.     break;
  505.     case 9:
  506.     code= cCUT;
  507.     break;
  508.     case 8:
  509.     code= cFIND;
  510.     break;
  511.     case 6:
  512.     code= cOPEN;
  513.     break;
  514.     }
  515.     if (code > 0)
  516.     return DoMenuCommand(code);
  517.     if (GetContainer())
  518.     return GetContainer()->DoFunctionKeyCommand(pfk, ContainerPoint(lp), t);
  519.     return gNoChanges;
  520. }
  521.  
  522. Command *VObject::DoMiddleButtonDownCommand(Point p, Token t, int clicks)
  523. {
  524.     if (GetContainer())
  525.     return GetContainer()->DoMiddleButtonDownCommand(ContainerPoint(p), t, clicks);
  526.     return gNoChanges;
  527. }
  528.  
  529. Command *VObject::DoLeftButtonDownCommand(Point p, Token t, int clicks)
  530. {
  531.     if (GetContainer())
  532.     return GetContainer()->DoLeftButtonDownCommand(ContainerPoint(p), t, clicks);
  533.     return gNoChanges;
  534. }
  535.  
  536. Command *VObject::DoOtherEventCommand(Point p, Token t)
  537. {
  538.     if (GetContainer())
  539.     return GetContainer()->DoOtherEventCommand(ContainerPoint(p), t);
  540.     return gNoChanges;
  541. }
  542.  
  543. Command *VObject::DoRightButtonDownCommand(Point lp, Token, int, Clipper *vf)
  544. {
  545.     Menu *menu;
  546.  
  547.     if (vf && (menu= GetMenu())) {
  548.     int cmdno;
  549.  
  550.     if (menu->IsNew())
  551.         DoCreateMenu(menu);                     // append menu items
  552.     menu->DisableAll();
  553.     DoSetupMenu(menu);                          // enable some menu items
  554.     if ((cmdno= menu->Show(lp, vf)) >= 0) {     // show menu in window
  555.         vf->Focus();
  556.         return DoMenuCommand(cmdno);
  557.     }
  558.     }
  559.     return gNoChanges;
  560. }
  561.  
  562. Command *VObject::TrackInContent(Point, Token, Command *currCmd)
  563. {
  564.     return currCmd;
  565. }
  566.  
  567. //---- misc --------------------------------------------------------------------
  568.  
  569. void VObject::Print()
  570. {
  571.     extern int ShowPrintDialog(VObject*);
  572.     
  573.     ShowPrintDialog(this);
  574. }
  575.  
  576. //---- VObjectCommand ----------------------------------------------------------
  577.  
  578. VObjectCommand::VObjectCommand(VObject *g) : Command(cIdNone)
  579. {
  580.     vop= g;
  581.     SetFlag(eCmdNoReplFeedback);
  582. }
  583.  
  584. void VObjectCommand::Init(VObject *g, Rectangle cr, Point gr, GrCursor cd, int hy)
  585. {
  586.     vop= g;
  587.     constrainRect= cr;
  588.     grid= gr;
  589.     newcursor= cd;
  590.     firstmove= FALSE;
  591.     hysterese= hy;
  592.     oldRect= newRect= vop->ContentRect();  
  593. }
  594.  
  595. Command *VObjectCommand::TrackMouse(TrackPhase atp, Point ap, Point, Point np)
  596. {
  597.     switch (atp) {
  598.     case eTrackPress:
  599.     oldcursor= GrGetCursor();
  600.     break;
  601.  
  602.     case eTrackRelease:
  603.     GrSetCursor(oldcursor);
  604.     
  605.     if (firstmove) {
  606.         if (vop->GetView() && !TestFlag(eCmdFullScreen))     
  607.         vop->SetContentRect(oldRect, FALSE);
  608.  
  609.         if (TestFlag(eCmdCanUndo))
  610.         break;
  611.         DoIt();
  612.     }
  613.     return gNoChanges;
  614.  
  615.     case eTrackMove:
  616.     delta= np - ap;
  617.     if (abs(delta.x) > hysterese || abs(delta.y) > hysterese) {
  618.         firstmove= TRUE;
  619.         GrSetCursor(newcursor);
  620.     }
  621.     break;
  622.     }
  623.     return this;
  624. }
  625.  
  626. void VObjectCommand::TrackConstrain(Point ap, Point, Point *np)
  627. {
  628.     Rectangle r= oldRect;
  629.  
  630.     r.origin+= *np-ap;
  631.     *np+= r.AmountToTranslateWithin(constrainRect);
  632.     if (grid >= 1)
  633.     *np= (*np/grid) * grid;     // align to grid
  634. }
  635.  
  636. void VObjectCommand::TrackFeedback(Point, Point, bool on)
  637. {
  638.     if (firstmove) {
  639.     if (port->penink != ePatXor) {
  640.         if (on)
  641.         vop->SetContentRect(newRect, TRUE);
  642.     } else
  643.         vop->Outline2(newRect.NW(), newRect.SE());
  644.     }
  645. }
  646.  
  647. void VObjectCommand::DoIt()
  648. {
  649.     vop->SetContentRect(newRect, !TestFlag(eCmdFullScreen));
  650. }
  651.  
  652. void VObjectCommand::UndoIt()
  653. {
  654.     vop->SetContentRect(oldRect, !TestFlag(eCmdFullScreen));
  655. }
  656.  
  657. //---- VObjectMover ------------------------------------------------------------
  658.  
  659. VObjectMover::VObjectMover(VObject *g) : VObjectCommand(g)
  660. {
  661.     Init(g, gRect0, gPoint1, eCrsMoveHand, 2);
  662. }
  663.  
  664. VObjectMover::VObjectMover(VObject *g, Rectangle cr) : VObjectCommand(g)
  665. {
  666.     Init(g, cr, gPoint1, eCrsMoveHand, 2);
  667. }
  668.  
  669. VObjectMover::VObjectMover(VObject *g, Rectangle cr, Point gr, GrCursor cd,
  670.                             int hy) : VObjectCommand(g)
  671. {
  672.     Init(g, cr, gr, cd, hy);
  673. }
  674.  
  675. void VObjectMover::Init(VObject *g, Rectangle cr, Point gr, GrCursor cd, int hy)
  676. {
  677.     SetName("move");
  678.     VObjectCommand::Init(g, cr, gr, cd, hy);
  679. }
  680.  
  681. Command *VObjectMover::TrackMouse(TrackPhase atp, Point ap, Point pp, Point np)
  682. {
  683.     Command *cmd= VObjectCommand::TrackMouse(atp, ap, pp, np);
  684.     switch (atp) {
  685.     case eTrackMove:
  686.     newRect= oldRect;
  687.     newRect.origin+= delta;
  688.     return this;
  689.     case eTrackRelease:
  690.     if (newRect == oldRect)
  691.         cmd= gNoChanges;
  692.     break;
  693.     }
  694.     return cmd;
  695. }
  696.  
  697. //---- VObjectStretcher --------------------------------------------------------
  698.  
  699. VObjectStretcher::VObjectStretcher(VObject *g) : VObjectCommand(g)
  700. {
  701.     Init(g, gRect0, gPoint1, eCrsMoveStretch, 2, g->GetMinSize());
  702. }
  703.  
  704. VObjectStretcher::VObjectStretcher(VObject *g, Rectangle cr) : VObjectCommand(g)
  705. {
  706.     Init(g, cr, gPoint1, eCrsMoveStretch, 2, g->GetMinSize());
  707. }
  708.  
  709. VObjectStretcher::VObjectStretcher(VObject *g, Rectangle cr, Point ms) : VObjectCommand(g)
  710. {
  711.     Init(g, cr, ms, eCrsMoveStretch, 2, g->GetMinSize());
  712. }
  713.  
  714. VObjectStretcher::VObjectStretcher(VObject *g, Rectangle cr, Point ms, Point gr,
  715.                     GrCursor cd, int hy) : VObjectCommand(g)
  716. {
  717.     Init(g, cr,  gr, cd, hy, ms);
  718. }
  719.  
  720. void VObjectStretcher::Init(VObject *g, Rectangle cr, Point gr,
  721.                         GrCursor cd, int hy, Point ms)
  722. {
  723.     SetName("resize");
  724.     VObjectCommand::Init(g, cr, gr, cd, hy);
  725.     minSize= ms;
  726. }
  727.  
  728. void VObjectStretcher::TrackConstrain(Point ap, Point, Point *np)
  729. {  
  730.     switch (corner) {
  731.     case 0: case 4:
  732.     np->x= ap.x;
  733.     break;
  734.     case 2: case 6:
  735.     np->y= ap.y;
  736.     break;
  737.     }
  738. }
  739.  
  740. Command *VObjectStretcher::TrackMouse(TrackPhase atp, Point ap, Point pp, Point np)
  741. {
  742.     Point p1, p2;
  743.  
  744.     switch (atp) {
  745.     case eTrackPress:
  746.     VObjectCommand::TrackMouse(atp, ap, pp, np);
  747.     corner= oldRect.PointToCorner(ap);
  748.     break;
  749.  
  750.     case eTrackMove:
  751.     VObjectCommand::TrackMouse(atp, ap, pp, np);
  752.     p1= oldRect.NW();
  753.     p2= oldRect.SE();
  754.  
  755.     switch (corner) {
  756.     case 0: case 6: case 7:
  757.         p1+= delta;
  758.         break;
  759.     case 1:
  760.         p2.x+= delta.x;
  761.         p1.y+= delta.y;
  762.         break;
  763.     case 5:
  764.         p1.x+= delta.x;
  765.         p2.y+= delta.y;
  766.         break;
  767.     default: // case 2: case 3: case 4:
  768.         p2+= delta;
  769.         break;
  770.     }
  771.     newRect= NormRect(p1, p2);
  772.     newRect.extent= Max(newRect.extent, minSize);
  773.     break;
  774.  
  775.     case eTrackRelease:
  776.     return VObjectCommand::TrackMouse(atp, ap, pp, np);
  777.     }
  778.     return this;
  779. }
  780.  
  781. //---- CompositeVObject --------------------------------------------------------------
  782.  
  783. AbstractMetaImpl(CompositeVObject, (TB(modified), TP(list), 0));
  784.  
  785. CompositeVObject::CompositeVObject(int id, Collection *cp) : VObject(id)
  786. {
  787.     list= cp;
  788.     if (list == 0)
  789.     list= new OrdCollection;
  790.     list->ForEach(VObject,SetContainer)(this);
  791.     modified= TRUE;
  792. }
  793.  
  794. CompositeVObject::CompositeVObject(int va_(id), ...) : VObject(va_(id))
  795. {
  796.     va_list ap;
  797.     va_start(ap,va_(id));
  798.     list= new OrdCollection;
  799.     SetItems(ap);
  800.     modified= TRUE;
  801.     va_end(ap);
  802. }
  803.  
  804. CompositeVObject::CompositeVObject(int id, va_list ap) : VObject(id)
  805. {
  806.     list= new OrdCollection;
  807.     SetItems(ap);
  808.     modified= TRUE;
  809. }
  810.  
  811. CompositeVObject::~CompositeVObject()
  812. {
  813.     SafeDelete(list);
  814. }
  815.  
  816. void CompositeVObject::FreeAll()
  817. {
  818.     if (list) {
  819.     list->FreeAll();
  820.     SafeDelete(list);
  821.     }    
  822. }
  823.  
  824. Collection *CompositeVObject::GetList()
  825. {
  826.     return list;
  827. }
  828.  
  829. int CompositeVObject::Size()
  830. {
  831.     if (list) 
  832.     return list->Size();
  833.     return 0;
  834. }
  835.  
  836. void CompositeVObject::Add(VObject *vop)
  837. {
  838.     if (vop) {
  839.     if (list == 0)
  840.         list= new OrdCollection;
  841.     list->Add(vop);
  842.     vop->SetContainer(this);
  843.     SetModified();
  844.     }
  845. }
  846.  
  847. VObject *CompositeVObject::Remove(VObject* vop)
  848. {
  849.     if (list) {
  850.     SetModified();
  851.     return (VObject*) list->Remove(vop);
  852.     }
  853.     return 0;
  854. }
  855.  
  856. VObject *CompositeVObject::SetAt(int at, VObject *vop)
  857. {
  858.     VObject *old= 0;
  859.     
  860.     if (vop) {
  861.     if (list->Size() > 0)
  862.         old= (VObject*) list->RemovePtr(At(at));
  863.     ((OrdCollection*)list)->AddAt(at, vop);
  864.     vop->SetContainer(this);
  865.     SetExtent(GetExtent());
  866.     SetOrigin(GetOrigin());
  867.     }
  868.     return old;
  869. }
  870.  
  871. Iterator *CompositeVObject::MakeIterator()
  872. {
  873.     if (list)
  874.     return list->MakeIterator();
  875.     return 0;
  876. }
  877.  
  878. void CompositeVObject::Open(bool mode)
  879. {
  880.     VObject::Open(mode);
  881.     if (list) {
  882.     list->ForEach(CompositeVObject,Open)(mode);
  883.     }
  884. }
  885.  
  886. void CompositeVObject::DoObserve(int, int, void*, Object *op)
  887. {
  888.     if (op == list)
  889.     SetModified();
  890. }
  891.  
  892. void CompositeVObject::SendDown(int id, int part, void *val)
  893. {
  894.     list->ForEach(VObject,SendDown)(id, part, val);
  895. }
  896.  
  897. void CompositeVObject::SetItems(va_list ap)
  898. {
  899.     list->AddVector(ap);
  900.     {
  901.     list->ForEach(VObject,SetContainer)(this);
  902.     }
  903. }
  904.  
  905. void CompositeVObject::SetContainer(VObject *v)
  906. {
  907.     VObject::SetContainer(v);
  908.     list->ForEach(VObject,SetContainer)(this);
  909. }
  910.  
  911. void CompositeVObject::Enable(bool b, bool redraw)
  912. {
  913.     VObject::Enable(b);
  914.     list->ForEach(VObject,Enable)(b, redraw);
  915. }
  916.  
  917. void CompositeVObject::Draw(Rectangle r)
  918. {
  919.     list->ForEach(VObject,DrawAll)(r, FALSE);
  920. }
  921.  
  922. void CompositeVObject::Outline2(Point p1, Point p2)
  923. {
  924.     list->ForEach(VObject,Outline2)(p1, p2);
  925. }
  926.  
  927. VObject *CompositeVObject::Detect(BoolFun find, void *arg)
  928. {
  929.     VObject *g1, *g2;
  930.     Iter next(list);
  931.  
  932.     while (g1= (VObject*) next())
  933.     if (g2= g1->Detect(find, arg))
  934.         return g2;
  935.     if (VObject::Detect(find, arg))
  936.     return (VObject*) this;
  937.     return 0;
  938. }
  939.  
  940. Command *CompositeVObject::DispatchEvents(Point lp, Token t, Clipper *vf)
  941. {
  942.     Command *cmd;
  943.     RevIter next((SeqCollection*)list);
  944.     VObject *dip;
  945.  
  946.     while (dip= (VObject*) next()) 
  947.     if (cmd= dip->Input(lp, t, vf))
  948.         return cmd;
  949.     return VObject::DispatchEvents(lp, t, vf);
  950. }
  951.  
  952. void CompositeVObject::SetOrigin(Point at)
  953. {
  954.     VObject::SetOrigin(at);
  955.     list->ForEach(VObject,SetOrigin)(at);
  956. }
  957.  
  958. void CompositeVObject::SetExtent(Point e)
  959. {
  960.     VObject::SetExtent(e);
  961.     list->ForEach(VObject,CalcExtent)();
  962. }
  963.  
  964. Metric CompositeVObject::GetMinSize()
  965. {
  966.     Metric m;
  967.     Iter next(list);
  968.     VObject *dip;
  969.  
  970.     while (dip= (VObject*) next())
  971.     m.Merge(dip->GetMinSize());
  972.     return m;
  973. }
  974.  
  975. int CompositeVObject::Base()
  976. {
  977.     return GetMinSize().base;
  978. }
  979.  
  980. ostream& CompositeVObject::PrintOn(ostream &s)
  981. {
  982.     VObject::PrintOn(s);
  983.     return s << list SP;
  984. }
  985.  
  986. istream& CompositeVObject::ReadFrom(istream &s)
  987. {
  988.     VObject::ReadFrom(s);
  989.     s >> list;
  990.     SetModified();
  991.     return s;
  992. }
  993.  
  994. void CompositeVObject::Parts(Collection* col)
  995. {
  996.     VObject::Parts(col);
  997.     col->Add(list);
  998. }
  999.  
  1000. void CompositeVObject::InspectorId(char *buf, int bufSize)
  1001. {
  1002.     VObject::InspectorId(buf, bufSize);
  1003. }
  1004.  
  1005.